﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GatherWebLib;
using System.Threading;
using GatherWebLib.Model;
using System.Data;
using Novel.Entity;
using Novel.Common;
using Novel.BizLogic.Base;

namespace Novel.BizLogic
{
    public class NovelGatherBll : GatherSubBase
    {
        public NovelGatherBll( bool isAllBook):base()
        {
           
            _isAllBook = isAllBook;
        }

        /// <summary>
        /// 最后抓取的更新时间
        /// </summary>
        private DateTime _LastGatherTime = DateTime.Now.Date;


        public bool _isAllBook;


        /// <summary>
        /// 线程锁
        /// </summary>
        private readonly Object m_threadLock = new Object();

        public void NovelGather()
        {
            try
            {

            
            ThreadPool.SetMaxThreads(20, 20);
           // GetNovelsbyqd();
              //GetChapterUrl();
              T_001GatherTaskLogBLLSub bll = new T_001GatherTaskLogBLLSub();
              //List<T_001GatherTaskLogEntity> novles = bll.GetUpdateNovels();
              //foreach (T_001GatherTaskLogEntity novel in novles)
              //{
              //    lock (m_threadLock)
              //    {

              //        WaitCallback w = new WaitCallback(GetNovelInfo);
              //        ThreadPool.QueueUserWorkItem(w, novel);

              //    }
              //}

              List<T_001GatherTaskLogEntity> novles1 = bll.GetNovelurls();
              foreach (T_001GatherTaskLogEntity novel1 in novles1)
              {
                  lock (m_threadLock)
                  {
                      WaitCallback w1 = new WaitCallback(GetNovelChapter);
                      ThreadPool.QueueUserWorkItem(w1, novel1);
                      Thread.Sleep(1000);
                  }
              }
            }
            catch (Exception e)
            {

                _Log(this, new LogArgs("", e.Message+e.StackTrace, true, cGlobalParas.LogType.Error));
            }
        }





        #region 小说抓取逻辑

        #region 抓取起点小说列表

      

        /// <summary>
        /// 抓取起点小说列表
        /// </summary>
        private void GetNovelsbyqd()
        {


            cTask_m task = GetTaskInfobyLevel(GatherWebLib.cGlobalParas.EnumNovelLevel.CmfuBookList);
            int index = 1;
            string url = task.WebpageLink[0].Weblink;
            DateTime _NextGatherTime = _LastGatherTime;
            while (true)
            {
                task.WebpageLink[0].Weblink = url.Replace("{pageIndex}", index.ToString());


                DataTable dt = Gather(task);
                if (dt != null && dt.Rows.Count > 0)
                {


                    if (task.TaskRunType == GatherWebLib.cGlobalParas.TaskRunType.GatherExportData && dt.Rows.Count > 0)
                    {
                        Publish(task.TaskID, dt);
                        //  InvokeMethod(this, "Publish", new object[] { task.TaskID, dt});
                    }

                    if (!_isAllBook)
                    {
                        if (index == 1)
                        {
                            _NextGatherTime = Convert.ToDateTime(dt.Rows[0]["更新时间"]);
                        }
                        if (Convert.ToDateTime(dt.Rows[dt.Rows.Count - 1]["更新时间"]) >= _LastGatherTime)
                        {
                            index++;
                        }
                        else
                        {
                            break;
                        }

                    }
                    else
                    {
                        index++;
                    }
                }
                else
                {
                    break;
                }

                _LastGatherTime = _NextGatherTime;
            }

        }

        #endregion


        #region 获取小说详情
        private void GetNovelInfo(object obj)
        {
            T_001GatherTaskLogEntity model = (T_001GatherTaskLogEntity)obj;
            cTask_m task = GetTaskInfobyLevel(GatherWebLib.cGlobalParas.EnumNovelLevel.CmfuBookInfo);
            string OldUrl = task.WebpageLink[0].Weblink.ToString();
            string Url = cTool.GetCompleteUrl(model.CmfuInfoUrl, OldUrl);
            task.WebpageLink[0].Weblink = Url;
            DataTable dt = Gather(task);
            if (dt != null && dt.Rows.Count > 0)
            {

                UpdateNovelIntro(dt.Rows[0], model.BookID);
                UpdateNovelCount(dt.Rows[0], model.BookID, model.CmfuListUrl);

            }
        }
        /// <summary>
        /// 更新小说详情介绍
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="bookID"></param>
        private void UpdateNovelIntro(DataRow dr, int bookID)
        {
            T_004NovelBLLSub bll = new T_004NovelBLLSub();

            T_004NovelEntity novel = new T_004NovelEntity();
            novel.BookID = bookID;
            novel.intro = dr["简介"].ToString();
            novel.Tags = dr["标签"].ToString();
            novel.author = dr["小说作者"].ToString();
            novel.Status = bll.GetWriteStatus(dr["写作进程"].ToString());
            bll.UpdateIntro(novel);
        }
        private void UpdateNovelCount(DataRow dr, int bookID, string listUrl)
        {
            T_005NovelInfoEntity NovelInfo = new T_005NovelInfoEntity();
            NovelInfo.BookID = bookID;
            NovelInfo.Hits = int.Parse(dr["总点击"].ToString());
            NovelInfo.MonthHits = int.Parse(dr["月点击"].ToString());
            NovelInfo.WeekHits = int.Parse(dr["周点击"].ToString());
            NovelInfo.Recommend = int.Parse(dr["总推荐"].ToString());
            NovelInfo.MonthRecommend = int.Parse(dr["月推荐"].ToString());
            NovelInfo.WeekRecommend = int.Parse(dr["周推荐"].ToString());
            NovelInfo.Length = int.Parse(dr["完成字数"].ToString());
            NovelInfo.CmfuChapterCount = GetNovelChapterCount(listUrl);
            T_005NovelInfoBLLSub bll = new T_005NovelInfoBLLSub();
            bll.UpdateHitCount(NovelInfo);
        }
        private int GetNovelChapterCount(string listUrl)
        {
            cTask_m task = GetTaskInfobyLevel(GatherWebLib.cGlobalParas.EnumNovelLevel.CmfuChapterList);
            string OldUrl = task.WebpageLink[0].Weblink;

            string Url = cTool.GetCompleteUrl(listUrl, OldUrl);
            task.WebpageLink[0].Weblink = Url;
            cGatherTask Gather = new cGatherTask(task);
            Gather.Log += tGather_Log;
            DataTable dt = Gather.Start();
            if (dt != null)
            {
                return dt.Rows.Count;
            }
            return 0;
        }
        #endregion


        #region 小说章节列表页地址
        private void GetChapterUrl()
        {
            T_001GatherTaskLogBLLSub log = new T_001GatherTaskLogBLLSub();
            int count = log.GetNewNovelCount();

           
            if (count > 0)
            {

                List<cTask_m> tasks = GetTasksbyLevel(GatherWebLib.cGlobalParas.EnumNovelLevel.OtherBookList);
                foreach (cTask_m t in tasks)
                {
                    GetChapterUrl(t);

                }
            }

        }

        private void GetChapterUrl(cTask_m task)
        {
            if (task.WebpageLink[0].Weblink.Contains("{pageIndex}"))
            {
                int index = 1;
                string url = task.WebpageLink[0].Weblink;
                cTask_m m=GetTaskInfoByfID(task.TaskID);
               
                if (m==null)
                {
                    _Log(this, new LogArgs(task.TaskName, "未找到下级任务", true, cGlobalParas.LogType.Gather));
                    return;
                }
                int taskID = m.TaskID;
                while (true)
                {
                    task.WebpageLink[0].Weblink = url.Replace("{pageIndex}", index.ToString());
                    DataTable dt = Gather(task);
                    if (dt != null && dt.Rows.Count > 0)
                    {


                        //   UpdateChapterUrl(dt, NewNovels, task.TaskID);
                        InvokeMethod(this, "UpdateChapterUrl", new object[] { dt, m.TaskID, task.TaskName, index });
                        if (!_isAllBook)
                        {
                            if (Convert.ToDateTime(dt.Rows[dt.Rows.Count - 1]["更新时间"]) >= DateTime.Now.Date)
                            {
                                index++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            index++;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

        }
        public void UpdateChapterUrl(DataTable dt, int taskID, string taskName, int index)
        {
            try
            {


                _Log(this, new LogArgs(taskName, string.Format("开始发布第{0}页的信息", index.ToString()), true, cGlobalParas.LogType.Gather));
                foreach (DataRow dr in dt.Rows)
                {
                    string BookName = dr["名称"].ToString();
                    string Url = dr["地址"].ToString();

                    T_001GatherTaskLogBLLSub sub = new T_001GatherTaskLogBLLSub();
                    T_001GatherTaskLogEntity logmodel = sub.GetNovelbyName(BookName.Trim());

                
                    if (logmodel != null)
                    {
                        T_002BookGatherUrlBLLSub bll = new T_002BookGatherUrlBLLSub();
                        T_002BookGatherUrlEntity model = new T_002BookGatherUrlEntity();
                        model.BookID = logmodel.BookID;
                        model.BookName = BookName;
                        model.TaskID = taskID;
                        model.BookListUrl = Url;
                        model.LastChapterUrl = "";
                        bll.Save(model);
                        sub.UpdateListUrlStatus(logmodel.BookID);
                    }
                }
               
                _Log(this, new LogArgs(taskName, string.Format("第{0}页的信息发布完成", index.ToString()), true, cGlobalParas.LogType.Gather));
            }
            catch (System.Exception ex)
            {
              
                _Log(this, new LogArgs(taskName, ex.Message + ex.StackTrace.ToString(), true, cGlobalParas.LogType.Error));
            }
        }

        #endregion


        #region 章节内容
        private void GetNovelChapter(object obj)
        { T_001GatherTaskLogEntity model = (T_001GatherTaskLogEntity)obj;
            try
            {

           
           

            if (model.TaskID != 0)
            {

                bool re = GetChapterContent(ref model, model.TaskID);
                if (!re)
                {
                    GetChapter(model, model.TaskID);
                }
            }
            else
            {
                GetChapter(model, 0);
            }
            }
            catch (Exception e)
            {

                _Log(this, new LogArgs("", e.Message + e.StackTrace, true, cGlobalParas.LogType.Error));
            }
        }


        private void GetChapter(T_001GatherTaskLogEntity log, int taskID)
        {

            List<cTask_m> tasks = GetTasksbyLevel(GatherWebLib.cGlobalParas.EnumNovelLevel.OtherChapterList, taskID);
            if (tasks != null && tasks.Count > 0)
            {
                foreach (cTask_m t in tasks)
                {
                    if (GetChapterContent(ref log, t.TaskID))
                    {
                        break;
                    }
                }
            }
        }

        private bool GetChapterContent(ref T_001GatherTaskLogEntity log, int TaskID)
        {
            bool resl = false;
            T_002BookGatherUrlBLLSub GatherUrlBLL = new T_002BookGatherUrlBLLSub();
            T_002BookGatherUrlEntity GatherUrl = GatherUrlBLL.GetObjectByTaskIDandBookID(log.BookID, TaskID);
            if (GatherUrl == null)
            {
                return false;
            }
            string url = UrlHelper.GetCompleteUrl(GatherUrl.BookListUrl);


            cTask_m tasks3 = GetTaskInfo(TaskID);
            tasks3.WebpageLink[0].Weblink = url;
            tasks3.WebpageLink[0].StartPos = string.IsNullOrEmpty(log.LastChapterTitle) ? "" : log.LastChapterTitle;

            DataTable ChapterList = Gather(tasks3);

            if (ChapterList != null && ChapterList.Rows.Count > 0)
            {
                int order = log.ChaptersCount;
                string LastChapterUrl = "";
                string LastChapterTitle = "";
                foreach (DataRow dr in ChapterList.Rows)
                {
                    if (!string.IsNullOrEmpty(dr["地址"].ToString()))
                    {
                        order++;
                        string u = cTool.GetCompleteUrl(dr["地址"].ToString(), url);
                        string title = dr["章节名"].ToString();
                        LastChapterUrl = u;
                        LastChapterTitle = title;
                      

                        AddParam param = new AddParam(tasks3.TaskID, log, title, order, u);
                        GetChapterContent(param);
                        //WaitCallback w = new WaitCallback(GetChapterContent);
                        //ThreadPool.QueueUserWorkItem(w, param);
                    }
                    
                }
                T_001GatherTaskLogBLLSub TaskLog = new T_001GatherTaskLogBLLSub();
                log.UpdateStatus = T_001GatherTaskLogEntity.EnumUpdateStatus.NoUpdate;
                log.TaskID = TaskID;
                log.LastChapterUrl = LastChapterUrl;
                log.LastChapterTitle = LastChapterTitle;
               
                log.ChaptersCount = order;
                if (log.ChaptersCount >= log.CmfuChapterCount)
                {
                    log.UpdateStatus = T_001GatherTaskLogEntity.EnumUpdateStatus.Updated;
                    resl = true;
                }
                TaskLog.UpdateStatus(log);
                _Log(this, new LogArgs(tasks3.TaskName, log.BookName + string.Format("更新了{0}章节，最后章节:{1}", ChapterList.Rows.Count,log.LastChapterTitle), true, cGlobalParas.LogType.Msg));
            }
           
            return resl;
        }

        private void GetChapterContent(object obj)
        {

            AddParam param = (AddParam)obj;

            int taskID = param.taskID;
            string url = param.Url;
            cTask_m task = GetTaskInfoByfID(taskID);
            task.WebpageLink[0].Weblink = url;
            T_001GatherTaskLogEntity log = param.log;
            string title = param.title;
            DataTable ContentList = Gather(task);
            if (ContentList != null && ContentList.Rows.Count > 0)
            {
                for (int i = 0; i < ContentList.Rows.Count; i++)
                {

                    DataRow content = ContentList.Rows[i];
                    Novel_ChapterBLLSub chbll = new Novel_ChapterBLLSub();
                    Novel_ChapterEntity chModel = new Novel_ChapterEntity();
                    chModel.BookID = log.BookID;
                    chModel.ChapterTitle = title;
                    chModel.ChapterContent = content["内容"].ToString();
                    chModel.Chapterby = param.index;
                    chbll.TableName = log.TableName;
                    chbll.Save(chModel);
                }
            }
        }


        #endregion

        #endregion

        /// <summary>
        /// 采集日志事件
        /// </summary>
        private event EventHandler<LogArgs> _Log;
        public event EventHandler<LogArgs> Novel_Log
        {
            add { _Log += value; }
            remove { _Log -= value; }
        }
    }
}
